﻿
using System.Text.RegularExpressions;

namespace Jitter2Process
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var path = Environment.CurrentDirectory;
            path += @"\..\..\..\..\";
            Console.WriteLine(Path.GetFullPath(path));
            bool isFixed = true;
            WriteJitter2(path, isFixed, false);
            WriteJitterDemo(path, isFixed);
        }

        private static void WriteJitterDemo(string path, bool isFixed)
        {
            //source: D:\jitterphysics2\src\JitterDemo
            var sourceDirectory = path + @"..\..\jitterphysics2\src\JitterDemo";
            sourceDirectory = Path.GetFullPath(sourceDirectory);
            var destinationDirectory = path + "JitterDemo";
            destinationDirectory = Path.GetFullPath(destinationDirectory);
            CopyDirectory(sourceDirectory, destinationDirectory);
            if (!isFixed)
                return;
            var files = Directory.GetFiles(destinationDirectory, "*.cs", SearchOption.AllDirectories);
            foreach (var file in files)
            {
                var textCode = File.ReadAllText(file);
                var namespaceIdx = textCode.IndexOf("namespace");
                if (namespaceIdx == -1)
                {
                    Console.WriteLine($"文件：{file}没有命名空间！");
                    continue;
                }
                var NS = isFixed ? "SoftFloat" : "MathX";
                var FLOAT = isFixed ? "sfloat" : "Float";
                var MATH = isFixed ? "libm" : "MathFloat";
                textCode = textCode.Replace($"= jmat.", $"= (float)jmat.");
                textCode = textCode.Replace($"= ori.", $"= (float)ori.");
                textCode = textCode.Replace($"= pos.", $"= (float)pos.");
                textCode = textCode.Replace($"(vector.X, vector.Y, vector.Z);", $"((float)vector.X, (float)vector.Y, (float)vector.Z);");
                textCode = textCode.Replace($"out float frac", $"out var frac");
                textCode = textCode.Replace($"protected override void WorldOnPostStep(float dt)", $"protected override void WorldOnPostStep({NS}.{FLOAT} dt)");
                textCode = textCode.Replace($"car.Velocity.Length();", $"(float)car.Velocity.Length();");
                textCode = textCode.Replace($"deepestFrac = frac;", $"deepestFrac = (float)frac;");
                textCode = textCode.Replace($"displacementForceMag *= JVector.Dot(groundNormal, worldAxis);", $"displacementForceMag *= (float)JVector.Dot(groundNormal, worldAxis);");
                textCode = textCode.Replace($"float sideVel = JVector.Dot(wheelPointVel, groundLeft);", $"float sideVel = (float)JVector.Dot(wheelPointVel, groundLeft);");
                textCode = textCode.Replace($"float fwdVel = JVector.Dot(wheelPointVel, groundFwd);", $"float fwdVel = (float)JVector.Dot(wheelPointVel, groundFwd);");
                textCode = textCode.Replace($"angVelForGrip = JVector.Dot(wheelCentreVel, groundFwd) / Radius;", $"angVelForGrip = (float)JVector.Dot(wheelCentreVel, groundFwd) / Radius;");
                textCode = textCode.Replace($"float maxOtherBodyForce = maxOtherBodyAcc * worldBody.Mass;", $"float maxOtherBodyForce = maxOtherBodyAcc * (float)worldBody.Mass;");
                textCode = textCode.Replace($"capsuleHalfHeight = cs.Radius + cs.Length * 0.5f;", $"capsuleHalfHeight = (float)cs.Radius + (float)cs.Length * 0.5f;");
                textCode = textCode.Replace($"var cs = new CapsuleShape();", $"var cs = new CapsuleShape(0.5f, 1.0f);");
                textCode = textCode.Replace($"newYVel += floorBody.Velocity.Y;", $"newYVel += (float)floorBody.Velocity.Y;");
                textCode = textCode.Replace($"float deltaVel = Body.Velocity.Y - newYVel;", $"float deltaVel = (float)Body.Velocity.Y - newYVel;");
                textCode = textCode.Replace($"float force = Body.Mass * deltaVel * 100.0f;", $"float force = (float)Body.Mass * deltaVel * 100.0f;");
                textCode = textCode.Replace($"float deltaMoveLen = deltaMove.Length();", $"float deltaMoveLen = (float)deltaMove.Length();");
                textCode = textCode.Replace($"volume += ((v2.Y - v1.Y) * (v3.Z - v1.Z) -", $"volume += (float)(((v2.Y - v1.Y) * (v3.Z - v1.Z) -");
                textCode = textCode.Replace($"(v2.Z - v1.Z) * (v3.Y - v1.Y)) * (v1.X + v2.X + v3.X);", $"(v2.Z - v1.Z) * (v3.Y - v1.Y)) * (v1.X + v2.X + v3.X));");
                textCode = textCode.Replace($"float fl2 = force.LengthSquared();", $"float fl2 = (float)force.LengthSquared();");
                textCode = textCode.Replace($"ref float penetration)", $"ref {NS}.{FLOAT} penetration)");
                textCode = textCode.Replace($"public override void CalculateMassInertia(out JMatrix inertia, out JVector com, out float mass)", $"public override void CalculateMassInertia(out JMatrix inertia, out JVector com, out {NS}.{FLOAT} mass)");
                textCode = textCode.Replace($"MathHelper.CloseToZero(position)", $"MathHelper.CloseToZero(position, 1e-16f)");
                textCode = textCode.Replace($"UpdateWorldBoundingBox();", $"UpdateWorldBoundingBox(0f);");
                textCode = textCode.Replace($"Math.Sign(direction", $"{NS}.{MATH}.Sign(direction");
                textCode = textCode.Replace($"(float)JAngle.FromDegree(40.0f);", $"(float)({NS}.{FLOAT})JAngle.FromDegree(40.0f);");
                textCode = textCode.Replace($"(1.0f / 12.0f) * mass * (sides.Y * sides.Y + sides.Z * sides.Z)", $"(float)((1.0f / 12.0f) * mass * (sides.Y * sides.Y + sides.Z * sides.Z))");
                textCode = textCode.Replace($"(1.0f / 12.0f) * mass * (sides.X * sides.X + sides.Z * sides.Z)", $"(float)((1.0f / 12.0f) * mass * (sides.X * sides.X + sides.Z * sides.Z))");
                textCode = textCode.Replace($"(1.0f / 12.0f) * mass * (sides.X * sides.X + sides.Y * sides.Y)", $"(float)((1.0f / 12.0f) * mass * (sides.X * sides.X + sides.Y * sides.Y))");
                textCode = textCode.Replace($"= Body.Mass", $"= (float)Body.Mass");
                textCode = textCode.Replace($"world.Gravity.Length()", $"(float)world.Gravity.Length()");
                textCode = textCode.Replace($"w.Spring * Body.Mass", $"w.Spring * (float)Body.Mass");
                textCode = textCode.Replace($"(float)damperJoints[Front", $"(float)({NS}.{FLOAT})damperJoints[Front");
                textCode = textCode.Replace($"b0.Velocity.LengthSquared() + b1.Velocity.LengthSquared()", $"(float)b0.Velocity.LengthSquared() + (float)b1.Velocity.LengthSquared()");
                textCode = textCode.Replace($"-world.Gravity.Y * (b0.Position.Y + b1.Position.Y);", $"(float)(-world.Gravity.Y * (b0.Position.Y + b1.Position.Y));");
                textCode = textCode.Replace($"MathF.Max(MathF.Max(delta.X, delta.Y), delta.Z);", $"MathF.Max(MathF.Max((float)delta.X, (float)delta.Y), (float)delta.Z);");
                textCode = textCode.Replace($"totalMass += cvhMass;", $"totalMass += (float)cvhMass;");
                textCode = textCode.Replace($"vertices[i].Texture = new Vector2(pos.X, pos.Z);", $"vertices[i].Texture = new Vector2((float)pos.X, (float)pos.Z);");
                textCode = textCode.Replace($"FatTriangleShape ts = new FatTriangleShape(jtm, i);", $"FatTriangleShape ts = new FatTriangleShape(jtm, i, 0.2f);");
                textCode = textCode.Replace($"b1.AddShape(new CapsuleShape(0.4f));", $"b1.AddShape(new CapsuleShape(0.4f, 1.0f));");
                textCode = textCode.Replace($" = JVector.Dot", $" = (float)JVector.Dot");
                textCode = textCode.Replace($"out float penetration", $"out var penetration");
                textCode = textCode.Replace($"CreateTranslation(pos.X, pos.Y, pos.Z),", $"CreateTranslation((float)pos.X, (float)pos.Y, (float)pos.Z),");
                textCode = textCode.Replace($"CreateScale(s.Size.X, s.Size.Y, s.Size.Z);", $"CreateScale((float)s.Size.X, (float)s.Size.Y, (float)s.Size.Z);");
                textCode = textCode.Replace($"CreateScale(s.Radius * 2);", $"CreateScale((float)s.Radius * 2);");
                textCode = textCode.Replace($"CreateScale(s.Radius, s.Height, s.Radius);", $"CreateScale((float)s.Radius, (float)s.Height, (float)s.Radius);");
                textCode = textCode.Replace($"CreateScale(s.Radius, s.Length, s.Radius);", $"CreateScale((float)s.Radius, (float)s.Length, (float)s.Radius);");
                textCode = textCode.Replace($"CreateTranslation(0, 0.5f * s.Length, 0) * MatrixHelper.CreateScale((float)s.Radius * 2);", $"CreateTranslation(0, 0.5f * (float)s.Length, 0) * MatrixHelper.CreateScale((float)s.Radius * 2);");
                textCode = textCode.Replace($"CreateScale(s.Radius * 2, s.Height, s.Radius * 2);", $"CreateScale((float)s.Radius * 2, (float)s.Height, (float)s.Radius * 2);");
                textCode = textCode.Replace($"new ConeShape()", $"new ConeShape(0.5f, 1.0f)");
                textCode = textCode.Replace($"out IDynamicTreeProxy? grepShape, out JVector _, out hitDistance);", $"out IDynamicTreeProxy? grepShape, out JVector _, out var hitDistance1);");
                textCode = textCode.Replace($"if (grepShape != null)", "hitDistance = (float)hitDistance1;\r\n\t\t\tif (grepShape != null)");
                textCode = textCode.Replace($"new ConeShape(1f);", $"new ConeShape(1f, 1.0f);");
                textCode = textCode.Replace($"World.DebugTimings.CopyTo(debugTimes, 0);", $"for (int i = 0; i < debugTimes.Length; i++) debugTimes[i] = (double)World.DebugTimings[i];");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                textCode = textCode.Replace($"JVector", $"NVector3");
                textCode = textCode.Replace($"JQuaternion", $"NQuaternion");
                File.WriteAllText(file, textCode);
            }
        }

        private static void WriteJitter2(string path, bool isFixed, bool is64Bit)
        {
            //source: D:\jitterphysics2\src\Jitter2
            var sourceDirectory = path + @"..\..\jitterphysics2\src\Jitter2";
            sourceDirectory = Path.GetFullPath(sourceDirectory);
            var destinationDirectory = path + "Jitter2";
            destinationDirectory = Path.GetFullPath(destinationDirectory);
            CopyDirectory(sourceDirectory, destinationDirectory);

            var files = Directory.GetFiles(destinationDirectory, "*.cs", SearchOption.AllDirectories);
            foreach (var file in files)
            {
                var fileName = Path.GetFileName(file);
                var textCode = File.ReadAllText(file);
                var index = textCode.IndexOf("namespace");
                if (index == -1)
                {
                    Console.WriteLine($"文件：{file}没有命名空间！");
                    continue;
                }
                if (fileName == "sfloat.cs" | fileName == "MathS.cs" | Path.GetDirectoryName(file).EndsWith("Expansions"))
                    continue;
                var FLOAT = isFixed ? "sfloat" : "float";
                var MATH = isFixed ? "libm" : "MathFloat";
                textCode = textCode.Insert(index, "using SoftFloat;\r\n\r\n");
                textCode = textCode.Replace("float", $"{FLOAT}");
                if (isFixed)
                    textCode = textCode.Replace("double", $"{FLOAT}");
                textCode = textCode.Replace("MathF", $"{MATH}");
                textCode = textCode.Replace("Math.", $"{MATH}.");
                textCode = textCode.Replace($"[assembly: InternalsVisibleTo(\"JitterTests\")]", $"//[assembly: InternalsVisibleTo(\"JitterTests\")]");
                if (isFixed)
                {
                    textCode = textCode.Replace($"    const {FLOAT} ", $"    {FLOAT} ");
                    textCode = textCode.Replace($" const {FLOAT} ", $" static {FLOAT} ");
                    textCode = textCode.Replace($"private volatile {FLOAT}", $"private /*volatile*/ {FLOAT}");
                    textCode = textCode.Replace($"({FLOAT} radius = 0.5f, {FLOAT} length = 1.0f)", $"({FLOAT} radius /*= 0.5f*/, {FLOAT} length /*= 1.0f*/)"); // length
                    textCode = textCode.Replace($"({FLOAT} radius = 0.5f, {FLOAT} height = 1.0f)", $"({FLOAT} radius /*= 0.5f*/, {FLOAT} height /*= 1.0f*/)"); // height
                    textCode = textCode.Replace($"{FLOAT} thickness = 0.2f", $"{FLOAT} thickness /*= 0.2f*/");
                    textCode = textCode.Replace($"{FLOAT} dt = 0.0f", $"{FLOAT} dt /*= 0.0f*/");
                    textCode = textCode.Replace($"UpdateWorldBoundingBox();", $"UpdateWorldBoundingBox({FLOAT}.Zero);");
                    textCode = textCode.Replace($"{FLOAT} radius = 1.0f", $"{FLOAT} radius /*= 1.0f*/");
                    textCode = textCode.Replace($"{FLOAT} epsilon = 1e-06f", $"{FLOAT} epsilon /*= 1e-06f*/");
                    textCode = textCode.Replace($"{FLOAT} epsilon = 1e-6f", $"{FLOAT} epsilon /*= 1e-6f*/");
                    textCode = textCode.Replace($"matrix.UnsafeGet(0)", $"matrix.UnsafeGet(0), epsilon");
                    textCode = textCode.Replace($"matrix.UnsafeGet(1)", $"matrix.UnsafeGet(1), epsilon");
                    textCode = textCode.Replace($"matrix.UnsafeGet(2)", $"matrix.UnsafeGet(2), epsilon");
                    textCode = textCode.Replace($"{FLOAT} epsilonSq = 1e-16f", $"{FLOAT} epsilonSq /*= 1e-16f*/");
                    textCode = textCode.Replace($"CloseToZero(vec)", $"CloseToZero(vec, 1e-16f)");
                    textCode = textCode.Replace($"TimeSpan.FromSeconds(deactivationTimeThreshold);", $"TimeSpan.FromSeconds((float)deactivationTimeThreshold);");
                    textCode = textCode.Replace($"deactivationTimeThreshold = ({FLOAT})value.TotalSeconds;", $"deactivationTimeThreshold = value == TimeSpan.MaxValue ? {FLOAT}.MaxValue : value == TimeSpan.MinValue ? {FLOAT}.MinValue : value.TotalSeconds;");
                    textCode = textCode.Replace($"IsRotationMatrix(transformation)", $"IsRotationMatrix(transformation, 1e-06f)");
                    textCode = textCode.Replace($"UnsafeIsZero(transformation - JMatrix.Identity)", $"UnsafeIsZero(transformation - JMatrix.Identity, 1e-6f)");

                    //Fix64 8字节
                    if (is64Bit)
                    {
                        textCode = textCode.Replace($"[StructLayout(LayoutKind.Explicit, Size = 36)]", $"[StructLayout(LayoutKind.Explicit, Size = 72)]");

                        textCode = textCode.Replace($"[FieldOffset(4)] public {FLOAT} M21;", $"[FieldOffset(8)] public {FLOAT} M21;");
                        textCode = textCode.Replace($"[FieldOffset(8)] public {FLOAT} M31;", $"[FieldOffset(16)] public {FLOAT} M31;");
                        textCode = textCode.Replace($"[FieldOffset(12)] public {FLOAT} M12;", $"[FieldOffset(24)] public {FLOAT} M12;");
                        textCode = textCode.Replace($"[FieldOffset(16)] public {FLOAT} M22;", $"[FieldOffset(32)] public {FLOAT} M22;");
                        textCode = textCode.Replace($"[FieldOffset(20)] public {FLOAT} M32;", $"[FieldOffset(40)] public {FLOAT} M32;");
                        textCode = textCode.Replace($"[FieldOffset(24)] public {FLOAT} M13;", $"[FieldOffset(48)] public {FLOAT} M13;");
                        textCode = textCode.Replace($"[FieldOffset(28)] public {FLOAT} M23;", $"[FieldOffset(56)] public {FLOAT} M23;");
                        textCode = textCode.Replace($"[FieldOffset(32)] public {FLOAT} M33;", $"[FieldOffset(64)] public {FLOAT} M33;");

                        textCode = textCode.Replace($"[StructLayout(LayoutKind.Sequential, Size = 12)]", $"[StructLayout(LayoutKind.Sequential, Size = 24)]");
                        textCode = textCode.Replace($"public const int ConstraintSize = 256;", $"public const int ConstraintSize = 512;");
                        textCode = textCode.Replace($"public const int ConstraintSize = 128;", $"public const int ConstraintSize = 256;");

                        textCode = textCode.Replace($"1e-12f", $"new {FLOAT}(1e-12f)");
                        textCode = textCode.Replace($"1e-22f", $"new {FLOAT}(1e-22f)");
                        textCode = textCode.Replace($"1e-16f", $"new {FLOAT}(1e-16f)");
                        textCode = textCode.Replace($"/*= new {FLOAT}(1e-16f)/*1e-16f*/*/", $"/*1e-16f*/");
                        textCode = textCode.Replace($"    {FLOAT} Epsilon = new {FLOAT}(1e-12f);", $"    {FLOAT} Epsilon = new {FLOAT}(1e-12f);");

                        textCode = textCode.Replace($"hit = d >= 0;", $"hit = d >= -0.1f; //精度问题");
                        textCode = textCode.Replace($"[StructLayout(LayoutKind.Sequential, Size = 48)]", $"[StructLayout(LayoutKind.Sequential, Size = 96)]");
                        textCode = textCode.Replace($"MemBlock48", $"MemBlock96");
                        textCode = textCode.Replace($"[StructLayout(LayoutKind.Sequential, Size = 64)]", $"[StructLayout(LayoutKind.Sequential, Size = 128)]");
                        textCode = textCode.Replace($"MemBlock64", $"MemBlock128");
                    }

                    textCode = textCode.Replace($"Debug.Assert(MathHelper.UnsafeIsZero(rigidBody.InverseInertiaWorld));", $"Debug.Assert(MathHelper.UnsafeIsZero(rigidBody.InverseInertiaWorld, 1e-6f));");
                    textCode = textCode.Replace($"System.Diagnostics.Debug.Assert(MathHelper.UnsafeIsZero(body.Data.InverseInertiaWorld));", $"System.Diagnostics.Debug.Assert(MathHelper.UnsafeIsZero(body.Data.InverseInertiaWorld, 1e-6f));");
                }
                // Unity兼容
                textCode = textCode.Replace($"public Triangle(int a, int b, int c)", $"public Triangle(int a, int b, int c) : this()");
                textCode = textCode.Replace($"public Vertex(JVector v)", $"public Vertex(JVector v) : this()");
                textCode = textCode.Replace($"private static ulong _idCounter;", $"private static long _idCounter;");
                textCode = textCode.Replace($"[Obsolete($\"{{nameof(ClearShapes)}} is deprecated, please use {{nameof(RemoveShape)}} instead.\")]", $"//[Obsolete($\"{{nameof(ClearShapes)}} is deprecated, please use {{nameof(RemoveShape)}} instead.\")]");
                textCode = textCode.Replace($"Debug.Assert(body.island is {{ bodies.Count: 1 }});", $"//Debug.Assert(body.island is {{ bodies.Count: 1 }});");
                textCode = textCode.Replace($"return Interlocked.Increment(ref _idCounter);", $"return (ulong)Interlocked.Increment(ref _idCounter);");
                textCode = textCode.Replace($"ulong count64 = (ulong)count;", $"long count64 = count;");
                textCode = textCode.Replace($"ulong max = Interlocked.Add(ref _idCounter, count64) + 1;", $"long max = Interlocked.Add(ref _idCounter, count64) + 1;");
                textCode = textCode.Replace($"return (max - count64, max);", $"return ((ulong)(max - count64), (ulong)max);");
                textCode = textCode.Replace($"private int index = -1;", $"private int index;// = -1;");
                textCode = textCode.Replace($"public Pair(int id1, int id2)", $"public Pair(int id1, int id2) : this()");
                textCode = textCode.Replace($"internal init;", $"internal set;");
                textCode = textCode.Replace($"if (!OperatingSystem.IsWindows() && Debugger.IsAttached)", $"if (false) //if (!OperatingSystem.IsWindows() && Debugger.IsAttached)");
                textCode = textCode.Replace($"ref Arbiter? arb = ", $"ref Arbiter arb = ");
                textCode = textCode.Replace($"public readonly bool IsLeaf => Proxy != null;", $"public bool IsLeaf => Proxy != null;");
                textCode = textCode.Replace($"Unsafe.SkipInit", $"UnsafeEx.SkipInit");
                textCode = textCode.Replace($"Active[batch.Start..batch.End];", $"Active.Slice(batch.Start, batch.End - batch.Start);");
                textCode = textCode.Replace($"return pool[^counter--];", $"return pool[pool.Count - counter--];");
                textCode = textCode.Replace($"NativeMemory.Alloc((nuint)len);", $"(void*)Marshal.AllocHGlobal(len);");
                textCode = textCode.Replace($"NativeMemory.Free(ptr);", $"Marshal.FreeHGlobal((nint)ptr);");
                textCode = textCode.Replace($"vertices = tmpVertices.ToArray();", "");
                textCode = textCode.Replace($"var tmpVerticesSpan = CollectionsMarshal.AsSpan(tmpVertices);", $"vertices = tmpVertices.ToArray();\r\n\t\tvar tmpVerticesSpan = new Span<CHullVector>(vertices);");
                textCode = textCode.Replace($"ref Arbiter arb = ref CollectionsMarshal.GetValueRefOrAddDefault(arbiters, arbiterKey, out bool exists);", $"ref Arbiter arb = ref arbiters.GetValueRefOrAddDefault(arbiterKey, out bool exists);");
                textCode = textCode.Replace($"private readonly Dictionary<ArbiterKey, Arbiter> arbiters = new();", $"private readonly SoftFloat.System.MyDictionary<ArbiterKey, Arbiter> arbiters = new(new ArbiterKeyComparer());");
                textCode = textCode.Replace($"return $\"{{X:F6}} {{Y:F6}} {{Z:F6}}\";", $"return $\"{{X.ToString(\"F6\")}} {{Y.ToString(\"F6\")}} {{Z.ToString(\"F6\")}}\";");
                textCode = textCode.Replace($"if (!float.IsNormal(idet))", $"if (!idet.IsNormal())");
                textCode = textCode.Replace($"private Random? optimizeRandom;", $"private Random optimizeRandom;");
                textCode = textCode.Replace($"optimizeRandom ??= new Random(0);", $"optimizeRandom ??= new Random(1752062104);");
                textCode = textCode.Replace($"point = JVector.Zero;", $"point = centerOffset;");
                textCode = textCode.Replace($"public event Action<Arbiter>? BeginCollide;", $"public Action<Arbiter> BeginCollide;");
                textCode = textCode.Replace($"public event Action<Arbiter>? EndCollide;", $"public Action<Arbiter> EndCollide;");
                textCode = textCode.Replace($"Debug.Assert({MATH}.Abs(n.LengthSquared() - 1.0f) < 1e-3);", $"//Debug.Assert({MATH}.Abs(n.LengthSquared() - 1.0f) < 1e-3);");
                //if (!textCode.Contains("public bool IsTriggered;", StringComparison.CurrentCulture))
                {
                    textCode = textCode.Replace("public bool IsTriggered;", "");
                    textCode = textCode.Replace($"public bool IsStatic;", $"public bool IsStatic;\r\n\tpublic bool IsTriggered;\r\n\tpublic CollisionLayer Layer;");
                    textCode = textCode.Replace($"if (rigidBody.IsStatic) continue;", $"if (rigidBody.IsStatic || rigidBody.IsTriggered) continue;");
                }
                textCode = textCode.Replace($"h *= 0x27d4eb2d;", $"h *= 668265261U;");
                textCode = textCode.Replace($"public struct JVector", $"public partial struct JVector");
                textCode = textCode.Replace($"public struct JQuaternion", $"public partial struct JQuaternion");
                textCode = textCode.Replace($"foreach (var constraint in body.constraints)", $"foreach (var constraint in body.constraints.ToArray()) //解决集合被修改错误");
                textCode = textCode.Replace($"foreach (var contact in body.contacts)", $"foreach (var contact in body.contacts.ToArray()) //解决集合被修改错误");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                //textCode = textCode.Replace($"", $"");
                textCode = Regex.Replace(textCode, @"\d+\.\d+[fd]", match =>
                {
                    return $"(sfloat){match.Value}";
                });
                index = textCode.IndexOf("public Enumerator(ActiveList<T> list)");
                if (index != -1)
                {
                    index = textCode.IndexOf("{", index);
                    textCode = textCode.Insert(index + 1, "\r\n\t\t\tindex = -1;");
                }
                index = textCode.IndexOf("public Enumerator(PairHashSet hashSet)");
                if (index != -1)
                {
                    index = textCode.IndexOf("{", index);
                    textCode = textCode.Insert(index + 1, "\r\n\t\t\tindex = -1;");
                }
                index = textCode.IndexOf("public override void SupportMap");
                if (index != -1)
                {
                    int count = 0;
                    for (int i = index; i < textCode.Length; i++)
                    {
                        if (textCode[i] == '{')
                        {
                            count++;
                        }
                        if (textCode[i] == '}')
                        {
                            count--;
                            if (count <= 0)
                            {
                                index = i;
                                break;
                            }
                        }
                    }
                    textCode = textCode.Insert(index, $"\r\n        result += centerOffset;// 应用中心偏移\r\n\t");
                }
                index = textCode.IndexOf("void CalculateBoundingBox(in JQuaternion orientation, in JVector position, out JBBox box)");
                if (index != -1)
                {
                    int count = 0;
                    for (int i = index; i < textCode.Length; i++)
                    {
                        if (textCode[i] == '{')
                        {
                            count++;
                        }
                        if (textCode[i] == '}')
                        {
                            count--;
                            if (count <= 0)
                            {
                                index = i;
                                break;
                            }
                        }
                    }
                    textCode = textCode.Insert(index, $"\r\n        // 考虑位置和中心偏移\r\n        box.Min += centerOffset;\r\n        box.Max += centerOffset;\r\n\t");
                }
                if (fileName == "RigidBody.cs")
                {
                    textCode = textCode.Replace("public bool IsTriggered { get => Data.IsTriggered; set => Data.IsTriggered = value; }", "");
                    //if (textCode.IndexOf("public bool IsTriggered") == -1)
                    {
                        index = textCode.IndexOf("public bool IsStatic", 2500);
                        if (index != -1)
                        {
                            int count = 0;
                            for (int i = index; i < textCode.Length; i++)
                            {
                                if (textCode[i] == '{')
                                {
                                    count++;
                                }
                                if (textCode[i] == '}')
                                {
                                    count--;
                                    if (count <= 0)
                                    {
                                        index = i;
                                        break;
                                    }
                                }
                            }
                            textCode = textCode.Insert(index + 3, $"\r\n\tpublic bool IsTriggered {{ get => Data.IsTriggered; set => Data.IsTriggered = value; }}\r\n\tpublic CollisionLayer Layer {{ get => Data.Layer; set => Data.Layer = value; }}");
                        }
                    }
                }
                textCode = textCode.Replace($"JVector", $"NVector3");
                textCode = textCode.Replace($"JQuaternion", $"NQuaternion");
                var textCodes = new List<string>(textCode.Split(new string[] { "\r\n" }, StringSplitOptions.None));
                int start = int.MaxValue;
                for (int i = 0; i < textCodes.Count; i++)
                {
                    if (textCodes[i].Contains("namespace Jitter2"))
                    {
                        textCodes[i] = textCodes[i].TrimEnd(';');
                        textCodes.Insert(i + 1, "{");
                        start = i + 2;
                        if (fileName == "JVector.cs")
                        {
                            textCodes.Insert(i + 6, "[Serializable]");
                        }
                        else if (fileName == "JQuaternion.cs")
                        {
                            textCodes.Insert(i + 6, "[Serializable]");
                        }
                        else if (fileName == "Shape.cs")
                        {
                            textCodes.Insert(73, @"    protected NVector3 centerOffset;
        /// <summary>
        /// Gets or sets the center offset of the capsule.
        /// </summary>
        public NVector3 CenterOffset
        {
            get => centerOffset;
            set
    
            {
                {
                    if (centerOffset == value)
                        return;
                    centerOffset = value;
                    UpdateWorldBoundingBox(0.0f);
                }
            }
        }
    
");
                        }
                        else if (fileName == "World.cs")
                        {
                            textCodes[27] = "using System.Linq;";
                        }
                        else if (fileName == "SimplexSolver.cs")
                        {
                            textCodes.Insert(47, $"\tpublic SimplexSolver()\r\n        {{\r\n        }}\r\n");
                        }
                        else if (fileName == "SimplexSolverAB.cs")
                        {
                            textCodes.Insert(64, $"\tpublic SimplexSolverAB()\r\n        {{\r\n        }}\r\n");
                        }
                    }
                    if (i >= start)
                    {
                        textCodes[i] = "\t" + textCodes[i];
                    }
                }
                if (fileName == "Arbiter.cs")
                {
                    var codeText = @"    public class ArbiterKeyComparer : IEqualityComparer<ArbiterKey>
    {
        public bool Equals(ArbiterKey x, ArbiterKey y)
        {
            return x == y;
        }

        public int GetHashCode(ArbiterKey obj)
        {
            return obj.GetHashCode();
        }
    }
    ";
                    textCodes.Add(codeText);
                }
                textCodes.Add("}");
                File.WriteAllLines(file, textCodes);
            }
        }

        static void CopyDirectory(string sourceDir, string destDir)
        {
            // 创建目标文件夹
            if (!Directory.Exists(destDir))
                Directory.CreateDirectory(destDir);

            // 复制所有文件
            foreach (string file in Directory.GetFiles(sourceDir, "*.cs"))
            {
                string destFile = Path.Combine(destDir, Path.GetFileName(file));
                File.Copy(file, destFile, true); // true 表示如果目标文件已存在，则覆盖
            }

            // 递归复制所有子文件夹
            foreach (string directory in Directory.GetDirectories(sourceDir))
            {
                var directoryInfo = new DirectoryInfo(directory);
                if (directoryInfo.Name == "obj" | directoryInfo.Name == "bin")
                    continue;
                string destSubDir = Path.Combine(destDir, Path.GetFileName(directory));
                CopyDirectory(directory, destSubDir);
            }
        }
    }
}
